<template>
    <div class="w100h100 p-2">
        <div class="mb10px">
            <div class="table-search-left">
                <el-input v-model="searchParams.projectName" style="width: 180px;" placeholder="请输入编制名称查询" clearable />
                <el-input v-model="searchParams.planName" style="width: 180px;" class="mlr10px" placeholder="请输入计划名称查询"
                    clearable />
                <el-button icon="Search" @click="getGanttInfo()">搜索</el-button>
                <el-button v-isSuperAdmin icon="Plus" @click="addPlan()">添加计划</el-button>
            </div>
            <div class="table-search-right">
            </div>
        </div>

        <div style="width: 100%;height: calc(100% - 50px);" class="justify-between">
            <div style="width: 14.5%;">
                <el-scrollbar height="100%">
                    <el-tree :data="deptList" :props="defaultProps" highlight-current default-expand-all
                        :expand-on-click-node="false" @node-click="nodeClick" />
                </el-scrollbar>
            </div>
            <div ref="ganttContainer" :class="$style.gantt"></div>
        </div>

        <el-drawer v-model="showDrawer1" size="500px" :title="title1" @close="close1()">
            <el-form ref="refPlanForm" :class="$style.form" :model="planForm" :rules="planFormRules" label-width="auto"
                label-position="right">
                <el-form-item label="编制名称：" prop="projectName">
                    <el-input v-model="planForm.projectName" placeholder="请输入编制名称" clearable />
                </el-form-item>
                <el-form-item label="版本号：">
                    <el-input v-model="planForm.version" readonly />
                </el-form-item>
                <el-form-item label="计划名称：" prop="planName">
                    <el-input v-model="planForm.planName" placeholder="请输入计划名称" clearable />
                </el-form-item>
                <el-form-item label="主计划：">
                    <el-select v-model="planForm.masterPlan" style="width: 100%;" :teleported="false">
                        <el-option label="否" value="0" />
                        <el-option label="是" value="1" />
                    </el-select>
                </el-form-item>
                <el-form-item label="开始时间：" prop="startDate">
                    <el-date-picker v-model="planForm.startDate" style="width: 100%;" type="datetime" placeholder="请选择开始时间"
                        value-format="YYYY-MM-DD HH:mm:ss" />
                </el-form-item>
                <el-form-item label="结束时间：" prop="endDate">
                    <el-date-picker v-model="planForm.endDate" style="width: 100%;" type="datetime" placeholder="请选择结束时间"
                        value-format="YYYY-MM-DD HH:mm:ss" />
                </el-form-item>
                <el-form-item label="备注：">
                    <el-input v-model="planForm.remarks" type="textarea" placeholder="请输入备注" autosize />
                </el-form-item>
                <el-form-item label="附件：">
                    <el-upload v-model:file-list="fileList" :action="uploadUrl" :headers="uploadHead" multiple
                        :before-upload="beforeUpload" :on-success="handleSuccess" :on-error="handleError"
                        :on-remove="handleRemove">
                        <el-button type="primary">上传文件</el-button>
                        <template #tip>
                            <div class="el-upload__tip">文件大小不超过10M</div>
                        </template>
                    </el-upload>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="showDrawer1 = false;">取消</el-button>
                <el-button type="primary" plain @click="submitPlanForm()">确定 </el-button>
            </template>
        </el-drawer>

        <el-drawer v-model="showDrawer2" size="500px" :title="title1" @close="close2()">
            <el-form ref="refTaskForm" :class="$style.form" :model="taskForm" :rules="taskFormRules" label-width="auto"
                label-position="right">
                <el-form-item label="任务名称：" prop="taskName">
                    <el-input v-model="taskForm.taskName" placeholder="请输入任务名称" clearable />
                </el-form-item>
                <el-form-item label="计划日期：" prop="date">
                    <el-date-picker v-model="taskForm.date" :class="$style.daterange" type="daterange"
                        value-format="YYYY-MM-DD" start-placeholder="开始日期" end-placeholder="完成日期"
                        :disabled-date="disabledDate" @change="selectDate">
                    </el-date-picker>
                </el-form-item>
                <el-form-item label="工期：">
                    <el-input-number v-model="taskForm.workDay" style="width: 100%;" disabled />
                </el-form-item>
                <el-form-item label="工时：">
                    <el-input-number v-model="taskForm.workTime" style="width: 100%;" :min="0" />
                </el-form-item>
                <el-form-item label="已完成百分比(%)：">
                    <el-input-number v-model="taskForm.completionPercentage" style="width: 100%;" :min="0" :max="100" />
                </el-form-item>
                <el-form-item label="限制类型:">
                    <el-select v-model="taskForm.restrictionType" style="width: 100%;">
                        <el-option v-for="ele of Object.keys(dic)" :key="ele" :label="dic[ele]" :value="ele" />
                    </el-select>
                </el-form-item>
                <el-form-item label="限制日期：">
                    <el-date-picker v-model="taskForm.restrictionDay" style="width: 100%;" placeholder="请选择限制日期"
                        value-format="YYYY-MM-DD" :disabled-date="disabledDate" />
                </el-form-item>
                <el-form-item label="备注：">
                    <el-input v-model="taskForm.remarks" type="textarea" placeholder="请输入备注" autosize />
                </el-form-item>
                <el-checkbox v-model="milestone" label="标记为里程碑" />
                <el-checkbox v-model="keyTask" label="标记为关键任务" />
            </el-form>
            <template #footer>
                <el-button @click="showDrawer2 = false;">取消</el-button>
                <el-button type="primary" plain @click="submitTaskForm()">确定</el-button>
            </template>
        </el-drawer>
    </div>
</template>

<script lang="ts" setup>
import { onMounted, reactive, ref } from 'vue';
import * as myHttp from '@/api/progress';
import { getDateStr } from '@/utils/misc';
import type { ElForm } from 'element-plus';
import { gantt } from 'dhtmlx-gantt';
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css';
import dayjs from 'dayjs';
import { UploadFile } from 'element-plus/es/components/upload/src/upload.type';
import { globalHeaders } from '@/utils/request';
import { listDept } from '@/api/system/dept';
import { useUserStore } from '@/store/modules/user';

type FormInstance = InstanceType<typeof ElForm>;

let formationId = 0;
let startDateStr: Date;
let endDateStr: Date;

const { roles } = useUserStore();
const hasRole = roles.every((role: string) => {
    return role !== 'superadmin';
});
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const baseUrl = import.meta.env.VITE_APP_BASE_API;
const uploadUrl = baseUrl + '/system/scheduleFormation/addFile';
const uploadHead = globalHeaders();
const tasks = { data: [], links: [], };
const planFormRules = {
    projectName: [{ required: true, message: '请输入编制名称', }],
    planName: [{ required: true, message: '请输入计划名称', }],
    executorId: [{ required: true, message: '请选择执行人员', }],
    superintendentId: [{ required: true, message: '请选择监督人员', }],
    startDate: [{ required: true, message: '请选择开始时间', }],
    endDate: [{ required: true, message: '请选择结束时间', }],
};
const taskFormRules = {
    taskName: [{ required: true, message: '请输入任务名称', }],
    executorId: [{ required: true, message: '请选择执行人员', }],
    reporterId: [{ required: true, message: "请选择上报人员", }],
    date: [{ required: true, message: "请选择计划日期", }],
};
const dic = {
    '1': '越早越好',
    '2': '越晚越好',
    '3': '必须开始于',
    '4': '必须完成于',
    '5': '不得早于..开始',
    '6': '不得晚于...开始',
    '7': '不得早于...完成',
    '8': '不得晚于...完成',
};
const defaultProps = {
    children: 'children',
    label: 'deptName',
};

const deptList = ref([]);
const searchParams = reactive({ deptId: '', projectName: '', planName: '', });
const ganttContainer = ref<HTMLElement>();

const showDrawer1 = ref(false);
const refPlanForm = ref<FormInstance>();
const title1 = ref('');
const planForm = ref({
    id: '', projectName: '', version: '', planName: '', masterPlan: '0',
    startDate: '', endDate: '', remarks: '', formationStatus: '0',
});
const fileList = ref([]);
const realFileList = ref([]);
const showButton = ref(true);

const showDrawer2 = ref(false);
const refTaskForm = ref<FormInstance>();
const taskForm = ref({
    id: '', parentId: '', taskName: '', workDay: 1, workTime: 0, completionPercentage: 0,
    date: [], restrictionType: '1', restrictionDay: '', remarks: '',
});
const milestone = ref(false);
const keyTask = ref(false);

const getDeptList = async () => {
    const res = await listDept();
    if (res.code == 200) {
        deptList.value = proxy?.handleTree(res.data, 'deptId');
    }
};

const nodeClick = async (event: any) => {
    searchParams.deptId = event.parentId ? event.deptId : '';
    getGanttInfo();
};

const init = () => {
    gantt.i18n.setLocale('cn');
    gantt.config.columns = [
        { name: 'text', label: '计划名称', width: '280', tree: true, },
        { name: 'add', align: 'center', width: '50', },
    ];
    gantt.config.scales = [
        { unit: 'month', step: 1, date: '%Y年%m月', css: () => 'scale-month', },
        { unit: 'day', step: 1, date: '%d', css: () => 'scale-day', },
    ];
    gantt.config.scale_height = 60;
    gantt.config.date_format = '%Y-%m-%d %H:%i:%s';
    gantt.templates.grid_header_class = () => 'scale-month';
    gantt.templates.task_text = (start, end, task) => `${task.text}（${Math.round(task.progress * 100)}%）`;
    gantt.plugins({
        tooltip: true,
    });
    gantt.templates.tooltip_text = (start, end, task) => {
        return `
            <div>${task.text}</div>
            <div>进度：${Math.round(task.progress * 100)}%</div>
            <div>开始时间：${getDateStr(start)}</div>
            <div>结束时间：${getDateStr(end, 0, 0, -1)}</div>
            <div>工期：${task.duration}天</div>
            ${(() => {
                if (task.progress !== 1 && end < new Date()) {
                    return `<div>已逾期${Math.ceil((Date.now() - end.getTime()) / 1000 / 3600 / 24)}天</div>`;
                }
                return '';
            })()}
        `;
    };
    gantt.templates.task_class = (start, end, task) => {
        if (task.progress !== 1 && end < new Date()) {
            return 'gantt-danger';
        }
        return 'gantt-primary';
    };
    gantt.config.smart_rendering = true;
    gantt.config.smart_scales = true;
    gantt.config.fit_tasks = true;
    gantt.centerTask = (id: string) => {
        const task = gantt.getTask(id);
        const taskPos = gantt.getTaskPosition(task);
        const centerPos = taskPos.left + taskPos.width / 2;
        const containerWidth = gantt.$root.clientWidth;
        gantt.scrollTo(centerPos - containerWidth / 2);
    };
    gantt.attachEvent('onTaskClick', (id) => {
        gantt.centerTask(id);
        return true;
    });
    gantt.attachEvent('onTaskRowClick', (id) => {
        gantt.centerTask(id);
        return true;
    });
    gantt.attachEvent('onTaskCreated', (task) => {
        if (!task.parent) {
            addPlan();
        } else {
            addTask(task.parent);
        }
        return false;
    });
    gantt.attachEvent('onTaskDblClick', (id) => {
        const task = gantt.getTask(id);
        if (!task.parent) {
            modifyPlan(id);
        } else {
            modifyTask(task.parent, task.taskId);
        }
        return false;
    });
    gantt.clearAll();
    gantt.init(ganttContainer.value!);
    getGanttInfo();
};

const addPlan = () => {
    planForm.value.version = dayjs().format('[ZM_]YYYYMMDDHHmm');
    title1.value = '添加计划';
    showDrawer1.value = true;
};

const modifyPlan = async (id: any) => {
    const res = await myHttp.getPlanDetail(id);
    if (res.code == 200) {
        const {
            projectName, version, planName, masterPlan,
            startDate, endDate, remarks, formationStatus, formationFiles,
        } = res.data;
        planForm.value = {
            id, projectName, version, planName, masterPlan,
            startDate, endDate, remarks, formationStatus,
        };
        formationFiles?.split(',').filter(ele => ele).forEach(ele => {
            const name = ele.split('/').pop() || '异常文件';
            fileList.value.push({ name, url: ele, });
            realFileList.value.push({ name, url: ele, });
        });
        title1.value = '修改计划信息';
        showDrawer1.value = true;
    }
};

const beforeUpload = (file: File) => {
    const isLt10MB = file.size < 10 * 1024 * 1024;
    if (!isLt10MB) {
        ElMessage.warning('上传文件大小不能超过 10MB');
    }
    return isLt10MB;
};

const handleSuccess = (res: any) => {
    realFileList.value.push({ url: res.data, });
};

const handleError = () => {
    ElMessage.error('上传失败,请重新上传');
};

const handleRemove = (uploadFile: UploadFile) => {
    const index = realFileList.value.findIndex(ele => [uploadFile.response?.result, uploadFile.url].includes(ele.url));
    if (index !== -1) {
        realFileList.value.splice(index, 1);
    }
};

const submitPlanForm = () => {
    refPlanForm.value?.validate(async () => {
        if (!planForm.value.id) {
            const res = await myHttp.addPlan({
                ...planForm.value,
                formationFiles: realFileList.value.map(ele => ele.url).join(','),
            });
            if (res.code == 200) {
                getGanttInfo();
                showDrawer1.value = false;
                ElMessage.success('添加成功');
            }
        } else {
            const res = await myHttp.modifyPlan({
                ...planForm.value,
                formationFiles: realFileList.value.map(ele => ele.url).join(','),
            });
            if (res.code == 200) {
                getGanttInfo();
                showDrawer1.value = false;
                ElMessage.success('修改信息成功');
            }
        }
    });
};

const getGanttInfo = async () => {
    const res = await myHttp.getGanttInfo(searchParams);
    if (res.code == 200) {
        tasks.data = res.data;
        tasks.data.forEach(ele => {
            ele.open = true;
        });
        gantt.clearAll();
        gantt.parse(tasks);
    }
}

const close1 = () => {
    fileList.value = [];
    realFileList.value = [];
    planForm.value = {
        id: '', projectName: '', version: '', planName: '', masterPlan: '0',
        startDate: '', endDate: '', remarks: '', formationStatus: '0',
    };
    refPlanForm.value?.resetFields();
    showButton.value = true;
}

const getFormationId = (id: string) => {
    const task = gantt.getTask(id);
    if (task.parent) {
        return getFormationId(task.parent);
    } else {
        taskForm.value.date = [dayjs(task.start_date).format('YYYY-MM-DD'), dayjs(task.start_date).format('YYYY-MM-DD')];
        startDateStr = task.start_date;
        endDateStr = task.end_date;
        return task.id;
    }
};

const addTask = async (parent: any) => {
    formationId = getFormationId(parent);
    taskForm.value.parentId = gantt.getTask(parent).id;
    title1.value = '添加任务';
    showDrawer2.value = true;
};

const modifyTask = async (parent: any, id: any) => {
    formationId = getFormationId(parent);
    const res = await myHttp.getTaskDetail(id);
    const {
        parentId, taskName, workDay, workTime, milestone: value1, keyTask: value2,
        completionPercentage, startTime, endTime, restrictionType, restrictionDay, remarks,
    } = res.data;
    taskForm.value = {
        id, parentId, taskName, workDay, workTime, completionPercentage,
        date: [startTime, endTime], restrictionType, restrictionDay, remarks,
    };
    milestone.value = value1 === '1';
    keyTask.value = value2 === '1';
    title1.value = '修改任务信息';
    showDrawer2.value = true;
};

const disabledDate = (data: Date) => {
    return data.getTime() < new Date(startDateStr).getTime() || data.getTime() >= new Date(endDateStr).getTime();
};

const selectDate = (event: any) => {
    taskForm.value.workDay = (new Date(event?.[1] ?? '') - new Date(event?.[0] ?? '')) / 3600000 / 24 + 1;
};

const submitTaskForm = () => {
    refTaskForm.value?.validate(async () => {
        if (!taskForm.value.id) {
            const res = await myHttp.addTask({
                ...taskForm.value,
                startTime: taskForm.value.date[0] ?? '',
                endTime: taskForm.value.date[1] ?? '',
                formationId: formationId,
                milestone: milestone.value ? '1' : '0',
                keyTask: keyTask.value ? '1' : '0',
            });
            if (res.code == 200) {
                getGanttInfo();
                showDrawer2.value = false;
                ElMessage.success('添加成功');
            }
        } else {
            const res = await myHttp.modifyTask({
                ...taskForm.value,
                startTime: taskForm.value.date[0] ?? '',
                endTime: taskForm.value.date[1] ?? '',
                formationId: formationId,
                milestone: milestone.value ? '1' : '0',
                keyTask: keyTask.value ? '1' : '0',
            });
            if (res.code == 200) {
                getGanttInfo();
                showDrawer2.value = false;
                ElMessage.success('修改信息成功');
            }
        }
    });
};

const close2 = () => {
    milestone.value = false;
    keyTask.value = false;
    taskForm.value = {
        id: '', parentId: '', taskName: '', workDay: 1, workTime: 0, completionPercentage: 0,
        date: [], restrictionType: '1', restrictionDay: '', remarks: '',
    };
    refTaskForm.value?.resetFields();
    showButton.value = true;
};

onMounted(() => {
    init();
    getDeptList();
});
</script>

<style lang="less">
.scale-month {
    font-size: 16px;
    font-weight: bold;
}

.scale-day {
    font-weight: bold;
}

.gantt-primary {
    background: #409eff;
}

.gantt-danger {
    background: #f56c6c;
}

.gantt-primary .gantt_task_progress,
.gantt-danger .gantt_task_progress {
    background: #67c23a;
}
</style>

<style lang="less" module>
.gantt {
    width: 85%;
    height: 100%;
}

// :global {

//     .gantt_container,
//     .gantt_grid_scale,
//     .gantt_task_scale,
//     .gantt_task_vscroll {
//         color: #FFF;
//         background: transparent;
//     }

//     .gantt_row,
//     .gantt_task_row,
//     .gantt_row.odd,
//     .gantt_task_row.odd {
//         background: transparent;

//         &:hover {
//             background: #00ddab !important;
//         }
//     }

//     .gantt_hor_scroll,
//     .gantt_ver_scroll {
//         scrollbar-color: #FFF rgba(39, 115, 229, 0.1);
//     }

//     .gantt_row.gantt_selected,
//     .gantt_task_row.gantt_selected,
//     .gantt_row.odd.gantt_selected,
//     .gantt_task_row.odd.gantt_selected {
//         background: #00ddab !important;
//     }

//     .gantt_last_cell::before,
//     .gantt_add::before {
//         color: #FFF;
//     }
// }
</style>
